Skip to content

Conversation

@JohnRichard4096
Copy link
Member

@JohnRichard4096 JohnRichard4096 commented Oct 23, 2025

Sourcery 摘要

通过添加类型注解、简化权限序列化、缓存节点权限以及启用权限修改的方法链式调用,对 Permissions 类进行了重构。

增强:

  • 为类属性和方法引入全面的类型提示
  • 重构内部权限转储,将 __dump_to_str 重命名为 __dump,并在 node_dict 中缓存数据
  • 调整 __search_perm 以返回结构化元组而非字符串行
  • 通过返回 Self 使 set_permissiondel_permission 可链式调用
  • 简化 check_permission 以利用预计算的 node_dict 实现更快的查找
  • 统一所有权限更新以调用 __dump 并移除冗余代码路径
Original summary in English

Summary by Sourcery

Refactor the Permissions class by adding type annotations, streamlining permission serialization, caching node permissions, and enabling method chaining for permission modifications.

Enhancements:

  • Introduce comprehensive type hints for class attributes and methods
  • Refactor internal permission dumping by renaming __dump_to_str to __dump and caching data in a node_dict
  • Adjust __search_perm to return structured tuples instead of string lines
  • Make set_permission and del_permission chainable by returning Self
  • Simplify check_permission to leverage the precomputed node_dict for faster lookups
  • Unify all permission updates to call __dump and remove redundant code paths

@sourcery-ai
Copy link

sourcery-ai bot commented Oct 23, 2025

评审指南

此 PR 重构了 Permissions 类,以添加带有 Self 返回的全面类型提示,将字符串转储整合到单个 __dump 方法中(该方法还会构建一个 node_dict 缓存),改进内部权限搜索以生成类型化元组,并通过利用支持通配符的 node_dict 来简化权限检查。

重构后的 Permissions 类的类图

classDiagram
class Permissions {
  dict[str, str | dict | bool] permissions_data
  dict[str, bool] node_dict
  str __permissions_str
  __init__(permissions_data: dict[str, str | dict | bool] | None)
  __str__()
  __search_perm(data: dict[str, Any], parent_key: str = "", result: list[tuple[str, bool]] | None = None) list[tuple[str, bool]]
  __dump(overwrite: bool = False)
  del_permission(node: str) Self
  set_permission(node: str, has_permission: bool, has_parent: bool = False) Self
  check_permission(node: str) bool
  dump_to_file(filename: str)
  load_from_json(filename: str)
  from_perm_str(perm_str: str)
  dump_data() dict[str, Any]
  data: dict[str, Any]
  perm_str: str
  permissions_str: str
}
Loading

使用 node_dict 和通配符进行权限检查逻辑的流程图

flowchart TD
    A["check_permission(node: str)"] --> B["node_dict.get(node)"]
    B -- True --> G["return True"]
    B -- False --> C["current_node = ''"]
    C --> D["for part in node.split('.')"]
    D --> E["node_dict.get(current_node + '.' + '*')"]
    E -- True --> G
    E -- False --> F["current_node += ('.' if current_node else '') + part"]
    F --> H["node_dict.get(current_node)"]
    H -- True --> G
    H -- False --> D
    D --> I["return False"]
Loading

文件级变更

变更 详情 文件
引入类型提示和 Self 返回注解
  • 从 typing_extensions 导入 Self
  • 注解类属性 (node_dict, __permissions_str)
  • 为 __search_perm 参数和返回类型添加类型提示
  • 声明 del_permission 和 set_permission 返回 Self
src/nonebot_plugin_liteperm/nodelib.py
将权限字符串转储统一到单个 __dump 方法中
  • 移除旧的 __dump_to_str 方法
  • 实现 __dump 以深度复制数据、构建 permissions_str 并填充 node_dict
  • 在 del_permission, set_permission, dump_to_file, load_from_json, data.setter, permissions_str 中,将所有对 __dump_to_str 的调用替换为 __dump
src/nonebot_plugin_liteperm/nodelib.py
重构 __search_perm 以返回类型化元组并构建 node_dict
  • 迭代 data.items() 而不是 keys
  • 将结果存储为 (path, bool) 元组而非格式化字符串
  • 在 __dump 中,解析这些元组以相应地填充 node_dict
src/nonebot_plugin_liteperm/nodelib.py
使用 node_dict 缓存简化 check_permission
  • 剥离输入节点字符串并查询 node_dict 以进行精确匹配
  • 通过连接片段并查找 ‘.*’ 模式来实现通配符检查
  • 移除先前的嵌套字典遍历逻辑
src/nonebot_plugin_liteperm/nodelib.py

提示和命令

与 Sourcery 互动

  • 触发新评审: 在拉取请求上评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的评审评论。
  • 从评审评论生成 GitHub issue: 通过回复 Sourcery 的评审评论,要求它创建一个 issue。您也可以回复评审评论并附上 @sourcery-ai issue 来从中创建一个 issue。
  • 生成拉取请求标题: 随时在拉取请求标题的任意位置写入 @sourcery-ai 以生成标题。您也可以在拉取请求上评论 @sourcery-ai title 以随时(重新)生成标题。
  • 生成拉取请求摘要: 随时在拉取请求正文的任意位置写入 @sourcery-ai summary 以在您想要的位置生成 PR 摘要。您也可以在拉取请求上评论 @sourcery-ai summary 以随时(重新)生成摘要。
  • 生成评审指南: 在拉取请求上评论 @sourcery-ai guide 以随时(重新)生成评审指南。
  • 解决所有 Sourcery 评论: 在拉取请求上评论 @sourcery-ai resolve 以解决所有 Sourcery 评论。如果您已经处理了所有评论并且不想再看到它们,这会很有用。
  • 驳回所有 Sourcery 评审: 在拉取请求上评论 @sourcery-ai dismiss 以驳回所有现有 Sourcery 评审。如果您想从头开始进行新的评审,这会特别有用——别忘了评论 @sourcery-ai review 以触发新的评审!

自定义您的体验

访问您的 控制面板 以:

  • 启用或禁用评审功能,例如 Sourcery 生成的拉取请求摘要、评审指南等。
  • 更改评审语言。
  • 添加、移除或编辑自定义评审说明。
  • 调整其他评审设置。

获取帮助

Original review guide in English

Reviewer's Guide

This PR refactors the Permissions class to add comprehensive type hints with Self returns, consolidate string dumping into a single __dump method that also builds a node_dict cache, improve the internal permission search to yield typed tuples, and simplify permission checks by leveraging the node_dict with wildcard support.

Class diagram for refactored Permissions class

classDiagram
class Permissions {
  dict[str, str | dict | bool] permissions_data
  dict[str, bool] node_dict
  str __permissions_str
  __init__(permissions_data: dict[str, str | dict | bool] | None)
  __str__()
  __search_perm(data: dict[str, Any], parent_key: str = "", result: list[tuple[str, bool]] | None = None) list[tuple[str, bool]]
  __dump(overwrite: bool = False)
  del_permission(node: str) Self
  set_permission(node: str, has_permission: bool, has_parent: bool = False) Self
  check_permission(node: str) bool
  dump_to_file(filename: str)
  load_from_json(filename: str)
  from_perm_str(perm_str: str)
  dump_data() dict[str, Any]
  data: dict[str, Any]
  perm_str: str
  permissions_str: str
}
Loading

Flow diagram for permission check logic with node_dict and wildcards

flowchart TD
    A["check_permission(node: str)"] --> B["node_dict.get(node)"]
    B -- True --> G["return True"]
    B -- False --> C["current_node = ''"]
    C --> D["for part in node.split('.')"]
    D --> E["node_dict.get(current_node + '.' + '*')"]
    E -- True --> G
    E -- False --> F["current_node += ('.' if current_node else '') + part"]
    F --> H["node_dict.get(current_node)"]
    H -- True --> G
    H -- False --> D
    D --> I["return False"]
Loading

File-Level Changes

Change Details Files
Introduce type hints and Self-return annotations
  • Import Self from typing_extensions
  • Annotate class attributes (node_dict, __permissions_str)
  • Add type hints to __search_perm parameters and return type
  • Declare del_permission and set_permission return Self
src/nonebot_plugin_liteperm/nodelib.py
Unify permission-string dumping into a single __dump method
  • Remove the old __dump_to_str method
  • Implement __dump to deep-copy data, build permissions_str, and populate node_dict
  • Replace all calls to __dump_to_str with __dump in del_permission, set_permission, dump_to_file, load_from_json, data.setter, permissions_str
src/nonebot_plugin_liteperm/nodelib.py
Refactor __search_perm to return typed tuples and build node_dict
  • Iterate over data.items() instead of keys
  • Store results as (path, bool) tuples rather than formatted strings
  • In __dump, parse these tuples to populate node_dict accordingly
src/nonebot_plugin_liteperm/nodelib.py
Simplify check_permission using the node_dict cache
  • Strip input node string and consult node_dict for exact matches
  • Implement wildcard checks by concatenating segments and looking for ‘.*’ patterns
  • Remove previous nested-dict traversal logic
src/nonebot_plugin_liteperm/nodelib.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@JohnRichard4096 JohnRichard4096 merged commit fec0260 into main Oct 23, 2025
1 of 2 checks passed
@JohnRichard4096 JohnRichard4096 deleted the JohnRichard4096-patch-2 branch October 23, 2025 09:59
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

你好 - 我已审阅了你的更改,它们看起来很棒!

AI 代理提示
请解决此代码审查中的评论:

## 单独评论

### 评论 1
<location> `src/nonebot_plugin_liteperm/nodelib.py:10` </location>
<code_context>

 class Permissions:
     permissions_data: dict[str, str | dict | bool]
+    node_dict: dict[str, bool]
+    __permissions_str: str = ""

</code_context>

<issue_to_address>
**问题 (bug_risk):** node_dict 未在 __init__ 中初始化,这可能导致在调用 __dump 之前使用时出现问题。

在调用 __dump 之前访问 node_dict 将引发 AttributeError。在 __init__ 中将 node_dict 初始化为空字典将防止这种情况发生。
</issue_to_address>

### 评论 2
<location> `src/nonebot_plugin_liteperm/nodelib.py:51-58` </location>
<code_context>
+        for n, v in self.__search_perm(data):
+            self.__permissions_str += f"{n} {'true' if v else 'false'}\n"
+            node_dict[n] = v
+        for line in self.__permissions_str.splitlines():
+            if line:
+                perm, arg = line.split(" ")
+                node_dict[perm] = arg == "true"
+        self.node_dict = node_dict
+
</code_context>

<issue_to_address>
**建议:** 冗余的 node_dict 填充:node_dict 已在之前的循环中填充。

第二个循环重复了第一个循环的工作,可以移除以简化代码并提高效率。

```suggestion
        for n, v in self.__search_perm(data):
            self.__permissions_str += f"{n} {'true' if v else 'false'}\n"
            node_dict[n] = v
        self.node_dict = node_dict
```
</issue_to_address>

### 评论 3
<location> `src/nonebot_plugin_liteperm/nodelib.py:106` </location>
<code_context>
    def check_permission(self, node: str) -> bool:
        node = node.strip()
        node_dict = self.node_dict
        if node_dict.get(node):
            return True
        current_node = ""
        for part in node.split("."):
            if node_dict.get(current_node + "." + "*"):
                return True
            current_node += ("." if current_node else "") + part
            if node_dict.get(current_node):
                return True
        return False

</code_context>

<issue_to_address>
**建议 (代码质量):** 使用 f-string 代替字符串拼接 [×2] ([`use-fstring-for-concatenation`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/use-fstring-for-concatenation/))

```suggestion
            if node_dict.get(f"{current_node}.*"):
```
</issue_to_address>

Sourcery 对开源项目免费 - 如果您喜欢我们的评论,请考虑分享 ✨
帮助我更有用!请点击每个评论上的 👍 或 👎,我将利用您的反馈来改进您的评论。
Original comment in English

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `src/nonebot_plugin_liteperm/nodelib.py:10` </location>
<code_context>

 class Permissions:
     permissions_data: dict[str, str | dict | bool]
+    node_dict: dict[str, bool]
+    __permissions_str: str = ""

</code_context>

<issue_to_address>
**issue (bug_risk):** node_dict is not initialized in __init__, which may cause issues if __dump is not called before usage.

Accessing node_dict before __dump is called will raise an AttributeError. Initializing node_dict in __init__ as an empty dict will prevent this.
</issue_to_address>

### Comment 2
<location> `src/nonebot_plugin_liteperm/nodelib.py:51-58` </location>
<code_context>
+        for n, v in self.__search_perm(data):
+            self.__permissions_str += f"{n} {'true' if v else 'false'}\n"
+            node_dict[n] = v
+        for line in self.__permissions_str.splitlines():
+            if line:
+                perm, arg = line.split(" ")
+                node_dict[perm] = arg == "true"
+        self.node_dict = node_dict
+
</code_context>

<issue_to_address>
**suggestion:** Redundant node_dict population: node_dict is already filled in the previous loop.

The second loop duplicates the work of the first and can be removed to simplify the code and improve efficiency.

```suggestion
        for n, v in self.__search_perm(data):
            self.__permissions_str += f"{n} {'true' if v else 'false'}\n"
            node_dict[n] = v
        self.node_dict = node_dict
```
</issue_to_address>

### Comment 3
<location> `src/nonebot_plugin_liteperm/nodelib.py:106` </location>
<code_context>
    def check_permission(self, node: str) -> bool:
        node = node.strip()
        node_dict = self.node_dict
        if node_dict.get(node):
            return True
        current_node = ""
        for part in node.split("."):
            if node_dict.get(current_node + "." + "*"):
                return True
            current_node += ("." if current_node else "") + part
            if node_dict.get(current_node):
                return True
        return False

</code_context>

<issue_to_address>
**suggestion (code-quality):** Use f-string instead of string concatenation [×2] ([`use-fstring-for-concatenation`](https://docs.sourcery.ai/Reference/Default-Rules/refactorings/use-fstring-for-concatenation/))

```suggestion
            if node_dict.get(f"{current_node}.*"):
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.


class Permissions:
permissions_data: dict[str, str | dict | bool]
node_dict: dict[str, bool]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

问题 (bug_risk): node_dict 未在 init 中初始化,这可能导致在调用 __dump 之前使用时出现问题。

在调用 __dump 之前访问 node_dict 将引发 AttributeError。在 init 中将 node_dict 初始化为空字典将防止这种情况发生。

Original comment in English

issue (bug_risk): node_dict is not initialized in init, which may cause issues if __dump is not called before usage.

Accessing node_dict before __dump is called will raise an AttributeError. Initializing node_dict in init as an empty dict will prevent this.

Comment on lines +51 to +58
for n, v in self.__search_perm(data):
self.__permissions_str += f"{n} {'true' if v else 'false'}\n"
node_dict[n] = v
for line in self.__permissions_str.splitlines():
if line:
perm, arg = line.split(" ")
node_dict[perm] = arg == "true"
self.node_dict = node_dict
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

建议: 冗余的 node_dict 填充:node_dict 已在之前的循环中填充。

第二个循环重复了第一个循环的工作,可以移除以简化代码并提高效率。

Suggested change
for n, v in self.__search_perm(data):
self.__permissions_str += f"{n} {'true' if v else 'false'}\n"
node_dict[n] = v
for line in self.__permissions_str.splitlines():
if line:
perm, arg = line.split(" ")
node_dict[perm] = arg == "true"
self.node_dict = node_dict
for n, v in self.__search_perm(data):
self.__permissions_str += f"{n} {'true' if v else 'false'}\n"
node_dict[n] = v
self.node_dict = node_dict
Original comment in English

suggestion: Redundant node_dict population: node_dict is already filled in the previous loop.

The second loop duplicates the work of the first and can be removed to simplify the code and improve efficiency.

Suggested change
for n, v in self.__search_perm(data):
self.__permissions_str += f"{n} {'true' if v else 'false'}\n"
node_dict[n] = v
for line in self.__permissions_str.splitlines():
if line:
perm, arg = line.split(" ")
node_dict[perm] = arg == "true"
self.node_dict = node_dict
for n, v in self.__search_perm(data):
self.__permissions_str += f"{n} {'true' if v else 'false'}\n"
node_dict[n] = v
self.node_dict = node_dict

return True
current_node = ""
for part in node.split("."):
if node_dict.get(current_node + "." + "*"):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

建议 (代码质量): 使用 f-string 代替字符串拼接 [×2] (use-fstring-for-concatenation)

Suggested change
if node_dict.get(current_node + "." + "*"):
if node_dict.get(f"{current_node}.*"):
Original comment in English

suggestion (code-quality): Use f-string instead of string concatenation [×2] (use-fstring-for-concatenation)

Suggested change
if node_dict.get(current_node + "." + "*"):
if node_dict.get(f"{current_node}.*"):

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants